package picturesender;

import com.gooddies.events.BooleanEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import javax.swing.JPanel;

public class DrawPanel extends JPanel {

    private Color drawColor = Color.RED;
    private final BufferedImage firstLayer = new BufferedImage(78, 39, BufferedImage.TYPE_3BYTE_BGR);
    private final BufferedImage secondLayer = new BufferedImage(78, 39, BufferedImage.TYPE_3BYTE_BGR);
    private final BufferedImage resultLayer = new BufferedImage(78, 39, BufferedImage.TYPE_3BYTE_BGR);
    private BooleanEvent onDrawEvent;
    public final Object lock = new Object();
    private final Color emptyColor = new Color(0x0, 0x00, 0x0);

    public DrawPanel() {
        clear();
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                synchronized (lock) {
                    int px = firstLayer.getWidth() * e.getX() / getWidth();
                    int py = firstLayer.getHeight() * e.getY() / getHeight();
                    firstLayer.setRGB(px, py, drawColor.getRGB());
                    repaint();
                    fireOnDraw();
                }
            }
        });

        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                synchronized (lock) {
                    int px = firstLayer.getWidth() * e.getX() / getWidth();
                    int py = firstLayer.getHeight() * e.getY() / getHeight();
                    if (px >= 0 && py >= 0 && px < firstLayer.getWidth() && py < firstLayer.getHeight()) {
                        firstLayer.setRGB(px, py, drawColor.getRGB());
                    }

                    repaint();
                    fireOnDraw();
                }
            }
        });
    }

    private void fireOnDraw() {
        if (onDrawEvent != null) {
            onDrawEvent.fireEvent(this);
        }
    }

    public void setDrawColor(Color drawColor) {
        this.drawColor = drawColor;
    }

    public void setOnDrawEvent(BooleanEvent onDrawEvent) {
        this.onDrawEvent = onDrawEvent;
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        synchronized (lock) {
            WritableRaster dest = resultLayer.getRaster();
            WritableRaster first = firstLayer.getRaster();
            WritableRaster second = secondLayer.getRaster();
            int[] val = new int[3];
            for (int j = 0; j < resultLayer.getHeight(); j++) {
                for (int i = 0; i < resultLayer.getWidth(); i++) {
                    second.getPixel(i, j, val);
                    dest.setPixel(i, j, val);
                    first.getPixel(i, j, val);
                    if (!(val[0] == 0x0 && val[1] == 0x0 && val[2] == 0x0)) {
                        dest.setPixel(i, j, val);
                    }
                }
            }

            g.drawImage(resultLayer, 0, 0, getWidth(), getHeight(), this);
        }
    }

    final public void clear() {
        Graphics g = firstLayer.getGraphics();
        g.setColor(emptyColor);
        g.fillRect(0, 0, firstLayer.getWidth(), firstLayer.getHeight());
        g.dispose();
    }

    public BufferedImage getFirstLayer() {
        return firstLayer;
    }

    public BufferedImage getSecondLayer() {
        return secondLayer;
    }
}